using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Castle.ActiveRecord;
using NHibernate.Expression;

namespace Natrue.Data.DataConversion
{
    public abstract class DifferentialAnalyseBase<Model>
    {
        //private bool isMatch;
        private readonly Model newBusinessObject;
        private readonly List<string> differentialProperties;


        protected DifferentialAnalyseBase(Model newBusinessObject, params string[] differentialProperties)
        {
            this.newBusinessObject = newBusinessObject;
            this.differentialProperties = new List<string>(differentialProperties);
        }

        public void Excute()
        {
            Model exitestObj = GetExitestObj(newBusinessObject);
            PropertyInfo[] properties = typeof (Model).GetProperties();
            if(Equals(exitestObj, default(Model)))
            {
                foreach (PropertyInfo info in properties)
                {
                    if (Attribute.IsDefined(info, typeof(BelongsToAttribute)) )
                    {
                        if(info.PropertyType.IsDefined(typeof(IDictionaryProperty), false))
                        {
                            DifferentialAnalyse tmp = new DifferentialAnalyse(info.DeclaringType, info.GetValue(newBusinessObject, null),
                                                                              "Caption");
                            info.SetValue(newBusinessObject, tmp.GetObject(), null);
                        }
                        else info.SetValue(newBusinessObject, null, null);
                    }
                }
                CreateModel(newBusinessObject);
                return;
            }

            foreach (PropertyInfo info in properties)
            {
                if (Attribute.IsDefined(info, typeof(BelongsToAttribute)))
                {
                    if (info.PropertyType.IsDefined(typeof(IDictionaryProperty), false))
                    {
                        DifferentialAnalyse tmp = new DifferentialAnalyse(info.DeclaringType, info.GetValue(newBusinessObject, null),
                                                                          "Caption");
                        info.SetValue(exitestObj, tmp.GetObject(), null);
                    }
                    else info.SetValue(exitestObj, null, null);
                }
                if (differentialProperties.Contains(info.Name))
                    info.SetValue(exitestObj, info.GetValue(newBusinessObject, null), null);
            }
            UpdateModel(exitestObj);
        }

        protected abstract Model GetExitestObj(Model record);
        protected abstract void CreateModel(Model model);
        protected abstract void UpdateModel(Model model);

    }

    public class DifferentialAnalyse
    {
        private Type modelType;
        //private ILocalAddinItemProxyContainer proxyContainer;
        private object newObj;
        private string[] checkSameKeys;

        internal DifferentialAnalyse(Type modelType, object newObj,params string[] checkSameKeys)
        {
            this.modelType = modelType;
            //this.proxyContainer = proxyContainer;
            this.newObj = newObj;
            this.checkSameKeys = checkSameKeys;
        }


        public object GetObject()
        {
            Queue<ICriterion> criterionQueue = new Queue<ICriterion>();
            foreach (string checkSameKey in checkSameKeys)
            {
                PropertyInfo propertyInfo = modelType.GetProperty(checkSameKey);
                if (propertyInfo == null) continue;
                criterionQueue.Enqueue(Expression.Eq(checkSameKey, propertyInfo.GetValue(newObj, null)).IgnoreCase());
            }
            IList result = ActiveRecordMediator.FindAll(modelType, Mussel.Data.OperationHelper.JointCriterionByAnd(criterionQueue));
            if (result == null || result.Count == 0)
            {
                CreateObj();
                return newObj;
            }
            return result[0];
        }

        private object GetExitestObj(object newObj)
        {
            return null;
        }

        private void CreateObj()
        {
            
            ActiveRecordMediator.Create(newObj);
        }

        private void SaveObj()
        {
            
        }
    }


}